using DimensionsHelper.Common.Contracts.TableFormatter;
using DimensionsHelper.Common.Contracts.Services;
using DimensionsHelper.Common.Utils;

namespace DimensionsHelper.Client.ViewModels.CsvFormatter;

public partial class CsvSubFileViewModel : FileInfoViewModel
{
    [ObservableProperty]
    private string _insertPosition = string.Empty;

    [ObservableProperty]
    private bool _isInsertFile = true;

    [ObservableProperty]
    private bool _isReplace;

    [ObservableProperty]
    private bool _replaceByIndex;

    [ObservableProperty]
    private bool _replaceByName;


    private bool _updatingInternal;

    public CsvSubFileViewModel()
    {
        PropertyChanged += OnIncompatiblePropertyChanged;
    }


    private void OnIncompatiblePropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (_updatingInternal)
        {
            return;
        }

        switch (e.PropertyName)
        {
            case nameof(IsReplace):
            {
                _updatingInternal = true;
                IsInsertFile = !IsReplace;
                _updatingInternal = false;
                break;
            }

            case nameof(IsInsertFile):
            {
                _updatingInternal = true;
                IsReplace = !IsInsertFile;
                _updatingInternal = false;
                break;
            }

            case nameof(ReplaceByIndex):
            {
                _updatingInternal = true;
                ReplaceByName = !ReplaceByIndex;
                _updatingInternal = false;
                break;
            }

            case nameof(ReplaceByName):
            {
                _updatingInternal = true;
                ReplaceByIndex = !ReplaceByName;
                _updatingInternal = false;
                break;
            }
        }
    }
}


public partial class CsvInputFileViewModel : FileInfoViewModel
{
    public int Index { get; internal set; }


    public ObservableCollection<CsvSubFileViewModel> SubFiles { get; } = [];

    public event Action<CsvInputFileViewModel>? MoveForward;

    public event Action<CsvInputFileViewModel>? MoveBackward;


    [RelayCommand]
    private void MoveSelfForward()
    {
        MoveForward?.Invoke(this);
    }


    [RelayCommand]
    private void MoveSelfBackward()
    {
        MoveBackward?.Invoke(this);
    }


    private void OnSubFileRemoveSelf(FileInfoViewModel subFile)
    {
        SubFiles.Remove((CsvSubFileViewModel)subFile);
    }


    private bool FileExist(string fileName)
    {
        return SubFiles.Any(f => f.FileName.Equals(fileName, StringComparison.OrdinalIgnoreCase));
    }


    [RelayCommand]
    private async Task SelectSubFiles()
    {
        IReadOnlyList<string> files = await App.GetService<IFilePikerService>()!.PickMultipleFilesAsync(FileFilters.Csv);

        if (files.Count == 0)
        {
            return;
        }

        foreach (string file in files)
        {
            if (FileExist(file))
            {
                continue;
            }

            CsvSubFileViewModel subFile = new()
            {
                Category = FileName,
                FileName = file,
                IsInsertFile = true
            };

            subFile.RemoveSelf += OnSubFileRemoveSelf;
            SubFiles.Add(subFile);
        }
    }


    public TableInputFileInfo ToCsvInputFileInfo()
    {
        List<TableInsertFileInfo> insertList = [];
        List<TableReplaceFileInfo> replaceList = [];

        foreach (CsvSubFileViewModel? subFile in SubFiles)
        {
            if (string.IsNullOrEmpty(subFile.FileName))
            {
                continue;
            }

            switch (subFile)
            {
                case { IsInsertFile: true, InsertPosition.Length: > 0 }:
                {
                    if (int.TryParse(subFile.InsertPosition, out int lineNumber))
                    {
                        insertList.Add(new TableInsertFileInfo
                        {
                            FileName = subFile.FileName,
                            LineNumber = lineNumber
                        });
                    }
                    else
                    {
                        insertList.Add(new TableInsertFileInfo
                        {
                            FileName = subFile.FileName,
                            TableName = subFile.InsertPosition
                        });
                    }

                    break;
                }

                case { IsReplace: true }:
                {
                    replaceList.Add(new TableReplaceFileInfo
                    {
                        FileName = subFile.FileName,
                        ByIndex = subFile.ReplaceByIndex,
                        ByName = subFile.ReplaceByName
                    });
                    break;
                }
            }
        }

        return new TableInputFileInfo(FileName, insertList, replaceList);
    }
}